/**
 *
 */
package de.cbf.cam.dsa.rcp.model.port;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import de.cbf.cam.dsa.rcp.model.entities.CultureDSA;
import de.cbf.cam.dsa.rcp.model.entities.ProfessionDSA;
import de.cbf.cam.dsa.rcp.model.entities.RaceDSA;
import de.cbf.cam.dsa.rcp.model.entities.StructureData;
import de.cbf.cam.dsa.rcp.model.port.act.ActivatorRCPImportExport;
import de.cbf.cam.dsa.rcp.model.port.exceptions.ImportException;
import de.cbf.cam.dsa.services.impl.rcp_provider.exceptions.PersisterConfigurationException;
import de.cbf.cam.dsa.services.impl.rcp_provider.extension.interfaces.IRCPPersisterCulture;
import de.cbf.cam.dsa.services.impl.rcp_provider.extension.interfaces.IRCPPersisterProfession;
import de.cbf.cam.dsa.services.impl.rcp_provider.extension.interfaces.IRCPPersisterRace;
import de.cbf.cam.dsa.services.impl.rcp_provider.extension.interfaces.IRCPPersisterStructure;
import de.cbf.cam.dsa.services.impl.rcp_provider.persister_service.IServiceRCPPersister;
import de.cbf.util.db.interfaces.exceptions.EntityLoadException;
import de.cbf.util.db.interfaces.exceptions.EntitySaveException;

/**
 * @author salter
 *
 */
public class ImportExporter {
	private static final Log logger = LogFactory.getLog(ImportExporter.class);

	protected IServiceRCPPersister persisterService;

	protected IRCPPersisterRace raceLoadPersister;
	protected IRCPPersisterRace raceSavePersister;

	protected IRCPPersisterCulture cultureLoadPersister;
	protected IRCPPersisterCulture cultureSavePersister;

	protected IRCPPersisterProfession professionLoadPersister;
	protected IRCPPersisterProfession professionSavePersister;

	protected IRCPPersisterStructure structureSavePersister;
	protected IRCPPersisterStructure structureLoadPersister;

	/**
	 *
	 */
	public ImportExporter() {
		persisterService = ActivatorRCPImportExport.getDefault().getPersisterService();
	}

	public void transferAll() throws ImportException {
		transferRaces();
		transferCultures();
		transferProfessions();
		transferStructureData();
	}

	public List<String> getRacePersisterNames(){
		List<String> result = new ArrayList<String>();
		List<IRCPPersisterRace> persisters = persisterService.getRacePersisters();
		for (IRCPPersisterRace persisterRace : persisters) {
			result.add(persisterRace.getName());
		}
		return result;
	}

	public void setImportRacePersister(String persisterName,Map<String,Object> parameters) throws PersisterConfigurationException{
		raceLoadPersister = findRacePersisterByName(persisterName);
		raceLoadPersister.setLoadParameters(parameters);
	}

	public void setExportRacePersister(String persisterName,Map<String,Object> parameters) throws PersisterConfigurationException{
		raceSavePersister = findRacePersisterByName(persisterName);
		raceSavePersister.setSaveParameters(parameters);
	}

	public void transferRaces() throws ImportException{
		boolean loadPersisterReady = raceLoadPersister != null;
		if( ! loadPersisterReady){
			throw new ImportException("Race load persister not ready");
		}
		boolean savePersisterReady = raceSavePersister != null;
		if( ! savePersisterReady){
			throw new ImportException("Race save persister not ready");
		}
		if(loadPersisterReady && savePersisterReady ){
			try {
				Collection<RaceDSA> races = raceLoadPersister.loadAllRaces();
				List<UUID> successfulImported = new ArrayList<UUID>();
				for (RaceDSA entity : races) {
					try {
						raceSavePersister.saveRace(entity);
						successfulImported.add(entity.getUuid());
					} catch (EntitySaveException e) {
						logger.error("Error in saving "+entity+" to "+raceSavePersister,e);
					}
				}
				raceLoadPersister.tidyUpRaces(successfulImported);
				raceSavePersister.tidyUpRaces(successfulImported);
			} catch (EntityLoadException e) {
				throw new ImportException("Error in loading of races from "+raceLoadPersister,e);
			}
		}
	}

	public IRCPPersisterRace findRacePersisterByName(String name)throws PersisterConfigurationException{
		List<IRCPPersisterRace> racePersisters = persisterService.getRacePersisters();
		for (IRCPPersisterRace persisterRace : racePersisters) {
			if(persisterRace.getName().equals(name)){
				return persisterRace;
			}
		}
		throw new PersisterConfigurationException("requested race persister not found: "+name);
	}

	public List<String> getCulturePersisterNames(){
		List<String> result = new ArrayList<String>();
		List<IRCPPersisterCulture> persisters = persisterService.getCulturePersisters();
		for (IRCPPersisterCulture persisterCulture : persisters) {
			result.add(persisterCulture.getName());
		}
		return result;
	}

	public void setImportCulturePersister(String persisterName,Map<String,Object> parameters) throws PersisterConfigurationException{
		cultureLoadPersister = findCulturePersisterByName(persisterName);
		cultureLoadPersister.setLoadParameters(parameters);
	}

	public void setExportCulturePersister(String persisterName,Map<String,Object> parameters) throws PersisterConfigurationException{
		cultureSavePersister = findCulturePersisterByName(persisterName);
		cultureSavePersister.setSaveParameters(parameters);
	}

	public void transferCultures() throws ImportException{
		boolean loadPersisterReady = cultureLoadPersister != null;
		if( ! loadPersisterReady){
			throw new ImportException("Load persister not ready");
		}
		boolean savePersisterReady = cultureSavePersister != null;
		if( ! loadPersisterReady){
			throw new ImportException("Save persister not ready");
		}
		if(loadPersisterReady && savePersisterReady ){

			try {
				Collection<CultureDSA> cultures = cultureLoadPersister.loadAllCultures();
				List<UUID> successfulImported = new ArrayList<UUID>();
				for (CultureDSA entity : cultures) {
					try {
						cultureSavePersister.saveCulture(entity);
						successfulImported.add(entity.getUuid());
					} catch (EntitySaveException e) {
						logger.error("Error in saving "+entity+" to "+cultureSavePersister,e);
					}
				}
				cultureLoadPersister.tidyUpCultures(successfulImported);
				cultureSavePersister.tidyUpCultures(successfulImported);
			} catch (EntityLoadException e) {
				throw new ImportException("Error in loading of cultures from "+cultureLoadPersister,e);
			}
		}
	}

	public IRCPPersisterCulture findCulturePersisterByName(String name)throws PersisterConfigurationException{
		List<IRCPPersisterCulture> culturePersisters = persisterService.getCulturePersisters();
		for (IRCPPersisterCulture persisterCulture : culturePersisters) {
			if(persisterCulture.getName().equals(name)){
				return persisterCulture;
			}
		}
		throw new PersisterConfigurationException("requested culture persister not found: "+name);
	}

	public List<String> getProfessionPersisterNames(){
		List<String> result = new ArrayList<String>();
		List<IRCPPersisterProfession> persisters = persisterService.getProfessionPersisters();
		for (IRCPPersisterProfession persisterProfession : persisters) {
			result.add(persisterProfession.getName());
		}
		return result;
	}

	public void setImportProfessionPersister(String persisterName,Map<String,Object> parameters) throws PersisterConfigurationException{
		professionLoadPersister = findProfessionPersisterByName(persisterName);
		professionLoadPersister.setLoadParameters(parameters);
	}

	public void setExportProfessionPersister(String persisterName,Map<String,Object> parameters) throws PersisterConfigurationException{
		professionSavePersister = findProfessionPersisterByName(persisterName);
		professionSavePersister.setSaveParameters(parameters);
	}

	public void transferProfessions() throws ImportException{
		boolean loadPersisterReady = professionLoadPersister != null;
		if( ! loadPersisterReady){
			throw new ImportException("Profession load persister not ready");
		}
		boolean savePersisterReady = professionSavePersister != null;
		if( ! loadPersisterReady){
			throw new ImportException("Profession save persister not ready");
		}
		if(loadPersisterReady && savePersisterReady ){

			try {
				Collection<ProfessionDSA> professions = professionLoadPersister.loadAllProfessions();
				List<UUID> successfulImported = new ArrayList<UUID>();
				for (ProfessionDSA entity : professions) {
					try {
						professionSavePersister.saveProfession(entity);
						successfulImported.add(entity.getUuid());
					} catch (EntitySaveException e) {
						logger.error("Error in saving "+entity+" to "+professionSavePersister,e);
					}
				}
				professionLoadPersister.tidyUpProfessions(successfulImported);
				professionSavePersister.tidyUpProfessions(successfulImported);
			} catch (EntityLoadException e) {
				throw new ImportException("Error in loading of professions from "+professionLoadPersister,e);
			}
		}
	}

	public IRCPPersisterProfession findProfessionPersisterByName(String name)throws PersisterConfigurationException{
		List<IRCPPersisterProfession> professionPersisters = persisterService.getProfessionPersisters();
		for (IRCPPersisterProfession persisterProfession : professionPersisters) {
			if(persisterProfession.getName().equals(name)){
				return persisterProfession;
			}
		}
		throw new PersisterConfigurationException("requested profession persister not found: "+name);
	}

	public List<String> getStructurePersisterNames(){
		List<String> result = new ArrayList<String>();
		List<IRCPPersisterStructure> persisters = persisterService.getStructurePersisters();
		for (IRCPPersisterStructure persisterStructure : persisters) {
			result.add(persisterStructure.getName());
		}
		return result;
	}

	public void setImportStructurePersister(String persisterName,Map<String,Object> parameters) throws PersisterConfigurationException{
		structureLoadPersister = findStructurePersisterByName(persisterName);
		structureLoadPersister.setLoadParameters(parameters);
	}

	public void setExportStructurePersister(String persisterName,Map<String,Object> parameters) throws PersisterConfigurationException{
		structureSavePersister = findStructurePersisterByName(persisterName);
		structureSavePersister.setSaveParameters(parameters);
	}

	public void transferStructureData() throws ImportException{
		boolean loadPersisterReady = structureLoadPersister != null;
		if( ! loadPersisterReady){
			throw new ImportException("structure load persister not ready");
		}
		boolean savePersisterReady = structureSavePersister != null;
		if( ! loadPersisterReady){
			throw new ImportException("structure save persister not ready");
		}
		if(loadPersisterReady && savePersisterReady ){
			try {
				Collection<StructureData> newStrutureDatas = structureLoadPersister.loadAllStructureData();
				//load structure from save persister too, to merge them
				Collection<StructureData> presentStructureDatas = structureSavePersister.loadAllStructureData();
				List<UUID> successfulImported = new ArrayList<UUID>();
				for (StructureData entityToAdd : newStrutureDatas) {
					try {
						//find structure data that has same UUID
						for (StructureData entityPresent : presentStructureDatas) {
							if(entityPresent.getUuid().toString().equals(entityToAdd.getUuid().toString())){
								//iterative adding of structure data
								entityPresent.mergeInRaceCultures(entityToAdd.getRaceCultures());
								entityPresent.mergeInCultureProfessions(entityToAdd.getCultureProfessions());
								//save
								structureSavePersister.saveStructure(entityPresent);
								successfulImported.add(entityToAdd.getUuid());
							}
						}
						if( ! successfulImported.contains(entityToAdd.getUuid())){
							//was not merged -> add as new
							structureSavePersister.saveStructure(entityToAdd);
							successfulImported.add(entityToAdd.getUuid());
						}
					} catch (EntitySaveException e) {
						logger.error("Error in saving "+entityToAdd+" to "+structureSavePersister,e);
					}
				}
				structureLoadPersister.tidyUpStructures(successfulImported);
				structureSavePersister.tidyUpStructures(successfulImported);
			} catch (EntityLoadException e) {
				throw new ImportException("Error in loading of structure from "+structureLoadPersister,e);
			}
		}
	}

	public IRCPPersisterStructure findStructurePersisterByName(String name)throws PersisterConfigurationException{
		List<IRCPPersisterStructure> structurePersisters = persisterService.getStructurePersisters();
		for (IRCPPersisterStructure persisterStructure : structurePersisters) {
			if(persisterStructure.getName().equals(name)){
				return persisterStructure;
			}
		}
		throw new PersisterConfigurationException("requested structure persister not found: "+name);
	}


}
